package com.pktechan.api.tradeOrderStatus;

import com.alibaba.fastjson.JSONObject;
import com.pktechan.api.dto.CommissionDTO;
import com.pktechan.api.entity.*;
import com.pktechan.api.enumeration.*;
import com.pktechan.api.exception.CustomException;
import com.pktechan.api.sendMiniMessage.BaseSendMiniMessage;
import com.pktechan.api.sendMiniMessage.SendMiniMessageStrategy;
import com.pktechan.api.sendMiniMessage.bean.CustomerDeliveryCompleteMessage;
import com.pktechan.api.sendMiniMessage.bean.FactoryDeliveryCompleteMessage;
import com.pktechan.api.sendMiniMessage.bean.ReferencesOrderMessage;
import com.pktechan.api.sendMiniMessage.enumration.SendMiniMessageEnum;
import com.pktechan.api.service.*;
import com.pktechan.api.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * @program: cloudfloating
 * @description: 配送完成
 * @author: qx.zhang
 * @create: 2021-03-15 11:27
 **/
@Component("completeOrder")
@Transactional
public class CompleteOrder extends BaseChangeTradeOrderState implements ChangeTradeOrderState {

    private final static Logger logger = LoggerFactory.getLogger(CompleteOrder.class);

    @Autowired
    private CommissionBalanceService commissionBalanceService;
    @Autowired
    private CommissionGenerateFlowService commissionGenerateFlowService;
    @Autowired
    private CloudPointService cloudPointService;
    @Autowired
    private CloudPointFlowService cloudPointFlowService;
    @Autowired
    private CloudTicketService cloudTicketService;
    @Autowired
    private CloudTicketFlowService cloudTicketFlowService;
    /**
     * 20240605 更新积分使用规则，不再为配送商使用了
     * 1)积分改为本次的酒钻规则，积分（酒钻）按产品参数给推荐人增加；
     *
     * @Autowired private CustCarriageService custCarriageService;
     * @Autowired private CustCarriageFlowService custCarriageFlowService;
     */

    @Autowired
    private TradeOrderDetailService tradeOrderDetailService;
    @Autowired
    private CustBaseService custBaseService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private SendMessageService sendMessageService;

    /**
     * 获取实现类对应的行为枚举
     *
     * @return
     */
    @Override
    public ChangeTradeOrderStatusEnum getMappingEnum() {
        return ChangeTradeOrderStatusEnum.COMPLETE_ORDER;
    }

    /**
     * 订单状态改变
     *
     * @param tradeOrderId
     * @param stateOld
     * @param stateCur
     * @param custId
     * @param exeRemark
     */
    @Override
    public void doChange(Integer tradeOrderId, Integer stateOld, Integer stateCur, Integer custId, String exeRemark) throws CustomException {
        TradeOrder tradeOrder = super.tradeOrderDataValidation(tradeOrderId);
        if (!TradeOrderStatusEnum.IN_DELIVERY.getCode().equals(tradeOrder.getStatus())) {
            logger.debug("订单ID为" + tradeOrderId + "对应的订单状态为" + TradeOrderStatusEnum.getNameByCode(tradeOrder.getStatus()) + "，不可完成");
            throw new CustomException("当前订单状态为" + TradeOrderStatusEnum.getNameByCode(tradeOrder.getStatus()) + "，不可完成");
        }
        logger.debug("配送完成" + "，订单ID：" + tradeOrderId + "，变更前状态：" + TradeOrderStatusEnum.IN_DELIVERY.getName() + "，变更后状态：" + TradeOrderStatusEnum.COMPLETED.getName()
                + "，操作人角色ID：" + custId + "，操作说明：" + exeRemark);


        //插入状态变化记录
        super.addTradeOrderStateFlow(tradeOrderId, stateOld, stateCur, custId, exeRemark);
        //更改订单状态
        super.updateTradeOrder(tradeOrderId, TradeOrderStatusEnum.COMPLETED.getCode());


        //后续1、变更客户身份等级提升
        this.doCustRankChange(tradeOrderId, tradeOrder.getCustId());

        //后续2、处理云积分-酒钻，设置酒钻获者ID为订单本人
        this.doPointChange(tradeOrderId, tradeOrder.getCustId());

        //后续3、处理酒票:设置酒票获者ID为订单的下单人
        this.doTicketHolder(tradeOrderId, tradeOrder.getCustId());

        //后续4、处理酒票、消耗推荐人1张酒票
        boolean tickerFlag = this.doTicketConsumer(tradeOrderId, tradeOrder.getBbId());
        //如果酒票不足，则无不进行后台更进，经确认，不能他发酒钱已事先讲好的，但酒票不足，则不进行后台更进;
        if (!tickerFlag) return;

        //后续5、遍历佣金需追溯的推荐级数，并为各级推荐人生成对应的佣金。20240604后，改为只有一级推荐人
        for (CommissionGenerationEnum commissionGenerationEnum : CommissionGenerationEnum.values()) {
            this.doCommissionChange(tradeOrderId, commissionGenerationEnum);
        }

        //后续6、发送能知短信，
        this.doSendMsg(tradeOrderId);

        /**
         *     20240605 更新积分使用规则，不再为配送商使用了
         *     1)积分改为本次的酒钻规则，积分（酒钻）只在提现待收货款成功之后，按一定的比例生成；

         //处理云积分
         CloudPoint cloudPoint = cloudPointService.getByCustId(tradeOrder.getDistributionCenterId());
         if (cloudPoint == null) {
         cloudPoint = new CloudPoint();
         cloudPoint.setAvailableBalance(BigDecimal.ZERO);
         cloudPoint.setCustId(tradeOrder.getDistributionCenterId());
         cloudPoint.setStatus(CloudPointStatusEnum.VALID.getCode());
         cloudPointService.save(cloudPoint);
         }
         List<CloudPointFlow> cloudPointFlowList = cloudPointFlowService.getGenerateListByTradeOrderId(tradeOrderId);
         for (CloudPointFlow cloudPointFlow : cloudPointFlowList) {
         //保存积分流水
         cloudPointFlow.setCloudPointId(cloudPoint.getId());
         cloudPointFlow.setBalancePre(cloudPoint.getAvailableBalance());
         cloudPointFlow.setBalanceAfter(cloudPoint.getAvailableBalance().add(cloudPointFlow.getAmount()));
         cloudPoint.setAvailableBalance(cloudPoint.getAvailableBalance().add(cloudPointFlow.getAmount()));
         cloudPointFlowService.save(cloudPointFlow);
         }


         //更新积分持仓
         cloudPointService.update(cloudPoint);


         //处理运费
         CustCarriage custCarriage = custCarriageService.getByCustId(tradeOrder.getDistributionCenterId());
         if (custCarriage == null) {
         custCarriage = new CustCarriage();
         custCarriage.setAvailableBalance(BigDecimal.ZERO);
         custCarriage.setCustId(tradeOrder.getDistributionCenterId());
         custCarriage.setStatus(CustCarriageStatusEnum.VALID.getCode());
         custCarriageService.save(custCarriage);
         }

         List<CustCarriageFlow> custCarriageFlowList = custCarriageFlowService.getGenerateListByTradeOrderId(tradeOrderId);
         //处理运费流水
         for (CustCarriageFlow custCarriageFlow : custCarriageFlowList) {
         custCarriageFlow.setCustCarriageId(custCarriage.getId());
         custCarriageFlow.setBalancePre(custCarriage.getAvailableBalance());
         custCarriageFlow.setBalanceAfter(custCarriage.getAvailableBalance().add(custCarriageFlow.getAmount()));
         custCarriage.setAvailableBalance(custCarriage.getAvailableBalance().add(custCarriageFlow.getAmount()));
         //流水保存
         custCarriageFlowService.save(custCarriageFlow);
         }
         custCarriageService.update(custCarriage);
         */

    }


    /**
     * 处理下单获取的酒票
     *
     * @param tradeOrderId
     * @param tickerHolder
     * @return
     */
    private void doTicketHolder(Integer tradeOrderId, Integer tickerHolder) {
        //获取酒票消费者的酒票持仓信息，无则创建持仓
        CloudTicket cloudTicketHoler = cloudTicketService.getByCustId(tickerHolder);
        if (cloudTicketHoler == null) {
            cloudTicketHoler = new CloudTicket();
            cloudTicketHoler.setAvailableBalance(BigDecimal.ZERO);
            cloudTicketHoler.setCustId(tickerHolder);
            cloudTicketHoler.setStatus(CloudPointStatusEnum.VALID.getCode());
            cloudTicketService.save(cloudTicketHoler);
        }
        List<CloudTicketFlow> cloudTicketFlowList = cloudTicketFlowService.getGenerateListByTradeOrderId(tradeOrderId);
        for (CloudTicketFlow cloudTicketFlow : cloudTicketFlowList) {
            //保存酒票流水
            cloudTicketFlow.setCloudTicketId(cloudTicketHoler.getId());
            cloudTicketFlow.setBalancePre(cloudTicketHoler.getAvailableBalance());
            cloudTicketFlow.setBalanceAfter(cloudTicketHoler.getAvailableBalance().add(cloudTicketFlow.getAmount()));

            cloudTicketHoler.setAvailableBalance(cloudTicketHoler.getAvailableBalance().add(cloudTicketFlow.getAmount()));
            cloudTicketFlowService.save(cloudTicketFlow);
        }
        //更新酒票持仓
        cloudTicketService.update(cloudTicketHoler);
    }

    /**
     * 处理下单消耗酒票业务
     * @param tradeOrderId
     * @param tickerConsumerId
     * @return
     */
    private boolean doTicketConsumer(Integer tradeOrderId, Integer tickerConsumerId) {
        boolean ticketFlag = true;
        //获取酒票消费者的酒票持仓信息，无则创建持仓
        CloudTicket cloudTicketConsumer = cloudTicketService.getByCustId(tickerConsumerId);
        if (cloudTicketConsumer == null) {
            cloudTicketConsumer = new CloudTicket();
            cloudTicketConsumer.setAvailableBalance(BigDecimal.ZERO);
            cloudTicketConsumer.setCustId(tickerConsumerId);
            cloudTicketConsumer.setStatus(CloudPointStatusEnum.VALID.getCode());
            cloudTicketService.save(cloudTicketConsumer);
        }

        //消耗推荐人1张酒票，无论订单多大，只消耗1张
        CloudTicketFlow ticketConsumerFlowTacker = new CloudTicketFlow();
        ticketConsumerFlowTacker.setCustId(cloudTicketConsumer.getCustId());
        ticketConsumerFlowTacker.setCloudTicketId(cloudTicketConsumer.getId());
        ticketConsumerFlowTacker.setTradeOrderId(tradeOrderId);
        ticketConsumerFlowTacker.setAmount(BigDecimal.ONE);
        ticketConsumerFlowTacker.setBalancePre(cloudTicketConsumer.getAvailableBalance());
        ticketConsumerFlowTacker.setBusinessType(CloudPointBusinessTypeEnum.CONSUMPTION.getCode());
        ticketConsumerFlowTacker.setStatus(CloudPointFlowStatusEnum.EFFECTIVE.getCode());
        cloudTicketFlowService.save(ticketConsumerFlowTacker);
        if (cloudTicketConsumer.getAvailableBalance().compareTo(BigDecimal.ONE) < 0) {
            //不扣为负数，到时只要判断流水里的转变前后都是0的就是欠票了的。
            ticketConsumerFlowTacker.setBalanceAfter(BigDecimal.ZERO);
            ticketFlag = false;
            logger.error("推荐人的酒票余额不足，无法消耗推荐人的酒票");
        }else{
            ticketConsumerFlowTacker.setBalanceAfter(cloudTicketConsumer.getAvailableBalance().subtract(BigDecimal.ONE));
        }
        //更新酒票持仓
        cloudTicketConsumer.setAvailableBalance(cloudTicketConsumer.getAvailableBalance().subtract(BigDecimal.ONE));
        cloudTicketService.update(cloudTicketConsumer);
        return ticketFlag;
    }



    private void doPointChange(Integer tradeOrderId, Integer pointHolderId) {
        CloudPoint cloudPoint = cloudPointService.getByCustId(pointHolderId);
        if (cloudPoint == null) {
            cloudPoint = new CloudPoint();
            cloudPoint.setAvailableBalance(BigDecimal.ZERO);
            cloudPoint.setCustId(pointHolderId);
            cloudPoint.setStatus(CloudPointStatusEnum.VALID.getCode());
            cloudPointService.save(cloudPoint);
        }
        List<CloudPointFlow> cloudPointFlowList = cloudPointFlowService.getGenerateListByTradeOrderId(tradeOrderId);
        for (CloudPointFlow cloudPointFlow : cloudPointFlowList) {
            //保存积分流水
            cloudPointFlow.setCustId(pointHolderId);
            cloudPointFlow.setCloudPointId(cloudPoint.getId());
            cloudPointFlow.setBalancePre(cloudPoint.getAvailableBalance());
            cloudPointFlow.setBalanceAfter(cloudPoint.getAvailableBalance().add(cloudPointFlow.getAmount()));
            cloudPoint.setAvailableBalance(cloudPoint.getAvailableBalance().add(cloudPointFlow.getAmount()));
            cloudPointFlowService.save(cloudPointFlow);
        }
        //更新积分持仓
        cloudPointService.update(cloudPoint);
    }

    private void doCommissionChange(Integer tradeOrderId, CommissionGenerationEnum commissionGenerationEnum) {
        //按订单明细，初始化佣金流水信息
        commissionGenerateFlowService.saveCommissionGenerateFlowByTradeOrderId(tradeOrderId, commissionGenerationEnum.getCode());
        //查询推荐人佣金总计
        CommissionDTO commissionDTO = commissionGenerateFlowService.getTotalCommissionByTradeOrderId(tradeOrderId, commissionGenerationEnum.getCode());
        if (commissionDTO == null) {
            return;
        }
        //根据客户ID查询佣金持仓
        CommissionBalance commissionBalance = commissionBalanceService.getByCustId(commissionDTO.getCustId());
        BigDecimal balancePre = BigDecimal.ZERO;
        if (commissionBalance == null) {
            //新建佣金持仓
            commissionBalance = new CommissionBalance();
            commissionBalance.setCustId(commissionDTO.getCustId());
            commissionBalance.setAvailableBalance(commissionDTO.getFeeTotal());
            commissionBalance.setDepositFreezeAmount(BigDecimal.ZERO);
            commissionBalance.setWithdrawFreezeAmount(BigDecimal.ZERO);
            commissionBalance.setStatus(CommissionBalanceStatusEnum.VALID.getCode());
            commissionBalanceService.save(commissionBalance);
        } else {
            //缓存变前佣金额
            balancePre = commissionBalance.getAvailableBalance().add(commissionBalance.getDepositFreezeAmount());
            //更新佣金持仓
            commissionBalance.setAvailableBalance(commissionBalance.getAvailableBalance().add(commissionDTO.getFeeTotal()));
            commissionBalanceService.update(commissionBalance);
        }

        //查询推荐人佣金列表
        List<CommissionGenerateFlow> commissionGenerateFlowList = commissionGenerateFlowService.getCommissionGenerateFlowListByTradeOrderId(tradeOrderId, commissionGenerationEnum.getCode());
        for (CommissionGenerateFlow commissionGenerateFlow : commissionGenerateFlowList) {
            commissionGenerateFlow.setBalancePre(balancePre);
            commissionGenerateFlow.setBalanceAfter(balancePre.add(commissionGenerateFlow.getFeeTotal()));
            //为下一条佣金流水重新设置变前佣金
            balancePre = balancePre.add(commissionGenerateFlow.getFeeTotal());
            commissionGenerateFlowService.update(commissionGenerateFlow);
        }
    }


    private void doCustRankChange(Integer tradeOrderId, Integer custId) {
        Integer orderVipRank = tradeOrderDetailService.getOrderVipRank(tradeOrderId);
        CustBase custBase = custBaseService.getById(custId);
        if(orderVipRank>custBase.getVipRank()){
            logger.info("客户购买高级产品，身份也升级");
            custBase.setVipRank(orderVipRank);
            custBaseService.update(custBase);
            redisService.setCustBaseByOpenId(custBase.getOpenId(), JSONObject.toJSONString(custBase));
        }

//        TradeOrderDetail tradeOrderDetail = tradeOrderDetailService.getRegisterOrderDetail(tradeOrderId);
//        if (tradeOrderDetail != null) {
//            //根据订单的业务类别修改客户的vip_type
//            if (BusinessTypeEnum.TOURIST_REGISTER_VIP.getBusinessType().equals(tradeOrderDetail.getBusinessType())) {
//                CustBase custBase = new CustBase();
//                custBase.setId(tradeOrderDetail.getCustId());
//                custBase.setVipType(VipTypeEnum.VIP.getCode());
//                custBaseService.update(custBase);
//            } else if (BusinessTypeEnum.VIP_REGISTER_DISTRIBUTOR.getBusinessType().equals(tradeOrderDetail.getBusinessType())) {
//                CustBase custBase = new CustBase();
//                custBase.setId(tradeOrderDetail.getCustId());
//                custBase.setVipType(VipTypeEnum.DISTRIBUTOR.getCode());
//                custBaseService.update(custBase);
//            }
//            //客户信息有修改，查询最新客户基本信息，将客户基本信息保存到redis中。
//            CustBase custBase = custBaseService.getById(tradeOrderDetail.getCustId());
//            redisService.setCustBaseByOpenId(custBase.getOpenId(), JSONObject.toJSONString(custBase));
//        }
    }

    private void doSendMsg(Integer tradeOrderId) {
        //配送完成通知
        CustomerDeliveryCompleteMessage customerDeliveryCompleteMessage = sendMessageService.getCustomerOrderDeliveryCompleteMessage(tradeOrderId);
        customerDeliveryCompleteMessage.setDeliveryTime(DateUtil.getCurrDateTime());
        SendMiniMessageStrategy customerDeliveryCompleteStrategy = BaseSendMiniMessage.getSendMiniMessage(SendMiniMessageEnum.CUSTOMER_DELIVERY_COMPLETE);
        customerDeliveryCompleteStrategy.sendMiniMessageToActiveMq(customerDeliveryCompleteMessage);
        //业绩确认通知
        ReferencesOrderMessage referencesOrderMessage = sendMessageService.getReferencesOrderMessage(tradeOrderId);
        SendMiniMessageStrategy referrerOrderCompleteStrategy = BaseSendMiniMessage.getSendMiniMessage(SendMiniMessageEnum.REFERRER_ORDER_COMPLETE);
        referrerOrderCompleteStrategy.sendMiniMessageToActiveMq(referencesOrderMessage);

        //厂家接收-配送商-完成配送-配送完成通知
        FactoryDeliveryCompleteMessage factoryDeliveryCompleteMessage = sendMessageService.getFactoryDeliveryCompleteMessage(tradeOrderId);
        SendMiniMessageStrategy factoryDeliveryCompleteStrategy = BaseSendMiniMessage.getSendMiniMessage(SendMiniMessageEnum.FACTORY_DELIVERY_COMPLETE);
        factoryDeliveryCompleteStrategy.sendMiniMessageToActiveMq(factoryDeliveryCompleteMessage);
    }
}
